/*
 *
 *  Copyright 2015-2016 the original author or authors.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *
 */
package com.zwl.swagger.plugins;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.Sets;
import com.zwl.swagger.CommentContainer;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.OperationBuilderPlugin;
import springfox.documentation.spi.service.contexts.OperationContext;
import springfox.documentation.spring.web.readers.operation.DefaultTagsProvider;
import springfox.documentation.swagger.common.SwaggerPluginSupport;

import java.util.HashSet;
import java.util.Set;

import static com.google.common.collect.FluentIterable.from;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.newTreeSet;
import static springfox.documentation.service.Tags.emptyTags;

/**
 * 接口类注释
 * @author zhangweilin
 * @Description:
 * @date 2021年08月20日 20:59
 */
@Component
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER)
@Slf4j
public class SwaggerOperationTagsReaderPlus implements OperationBuilderPlugin, ContextDescriper {

    private final DefaultTagsProvider tagsProvider;

    @Autowired
    CommentContainer commentContainer;

    @Autowired
    public SwaggerOperationTagsReaderPlus(DefaultTagsProvider tagsProvider) {
        this.tagsProvider = tagsProvider;
    }

    @Override
    public void apply(OperationContext context) {
        Set<String> defaultTags = tagsProvider.tags(context);
//        SetView<String> tags = union(operationTags(context), controllerTags(context));
//        if (tags.isEmpty()) {
//            context.operationBuilder().tags(defaultTags);
//        } else {
//            context.operationBuilder().tags(tags);
//        }

        //===
        String description = "";
        try {
            description = getClassDescription(context);
            if (StringUtils.isEmpty(description)) {
                context.operationBuilder().tags(defaultTags);
                return;
            }
            String comment = commentContainer.getClassCommentMap().get(description);
            if (StringUtils.isEmpty(comment)) {
                context.operationBuilder().tags(defaultTags);
                return;
            }
            Set<String> commentSet = new HashSet<>(1);
            commentSet.add(comment);
            context.operationBuilder().tags(commentSet);
        } catch (Exception e) {
			log.error("SwaggerOperationTagsReaderPlus异常,description: " + description,e);
        }
    }

    private Set<String> controllerTags(OperationContext context) {
        Optional<Api> controllerAnnotation = context.findControllerAnnotation(Api.class);
        return controllerAnnotation.transform(tagsFromController()).or(Sets.<String>newHashSet());
    }

    private Set<String> operationTags(OperationContext context) {
        Optional<ApiOperation> annotation = context.findAnnotation(ApiOperation.class);
        return annotation.transform(tagsFromOperation()).or(Sets.<String>newHashSet());
    }

    private Function<ApiOperation, Set<String>> tagsFromOperation() {
        return new Function<ApiOperation, Set<String>>() {
            @Override
            public Set<String> apply(ApiOperation input) {
                Set<String> tags = newTreeSet();
                tags.addAll(from(newArrayList(input.tags())).filter(emptyTags()).toSet());
                return tags;
            }
        };
    }

    private Function<Api, Set<String>> tagsFromController() {
        return new Function<Api, Set<String>>() {
            @Override
            public Set<String> apply(Api input) {
                Set<String> tags = newTreeSet();
                tags.addAll(from(newArrayList(input.tags())).filter(emptyTags()).toSet());
                return tags;
            }
        };
    }

    @Override
    public boolean supports(DocumentationType delimiter) {
        return true;
    }
}
